/**
 * 
 */
package czolgisci.display;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import utils.Sprite;


import utils.time.IClockListener;

import czolgisci.events.TickEvent;
import czolgisci.map.ISpritesIterator;

/**
 * Zarządza wyświetlaniem mapy gry. Zawiera iterator kontenera z obiektami do
 * wyświetlenia i pole do rysowania. Odbiera sygnały wysyłane przez zegar
 * (Clock). Gdy odbierze sygnał, wywoływana jest metoda render(), w której
 * poprzez użycie iteratora wyświetalne są wszystkie obiekty z kontenera.
 * 
 * @pattern Singleton
 * @author kasztan
 * @version 1.0
 */
public class DisplayManager implements IClockListener
{
	static private DisplayManager instance;

	private Graphics2D drawField;
	private ISpritesContainer spritesContainer;

	private DisplayManager()
	{
	}

	/**
	 * @param iterator
	 *            iterator kontenera, w ktorym trzymane sa obiekty do
	 *            wyświetlania
	 * @param drawField
	 *            pole, w ktorym wyswietlana jest gra
	 */
	public void init(ISpritesContainer spritesContainer, Graphics2D drawField)
	{
		this.drawField = drawField;
		this.spritesContainer = spritesContainer;
	}

	/**
	 * Metoda wyświetlająca aktualny stan gry na ekranie
	 * 
	 * @throws Exception
	 */
	public void render() throws Exception
	{
		if (drawField == null)
		{
			throw new Exception("drawField not defined");
		}
		
		// iterator po wszystkich obiektach na planszy
		ISpritesIterator imageIterator = spritesContainer.iterator();
		
		// tworzymy chwilowy obrazke na którym aktualizujemy rysujemy aktualny stan planszy
		BufferedImage image = new BufferedImage(spritesContainer.getWidth(), spritesContainer.getHeight(),BufferedImage.TYPE_INT_ARGB);
		Graphics2D screenTmp = image.createGraphics();
		
		while (imageIterator.hasNext())
		{
			// rysujemy wszystkie pozostałe obiekty
			Sprite tmp = imageIterator.next();
			screenTmp.drawImage(tmp.getImage(), null, tmp.getPoint().x, tmp.getPoint().y);
		}
		// wyświetlamy całość na ekranie
		drawField.drawImage(image, null, 0, 0);
	}

	/**
	 * Metoda wzorca Singleton
	 * 
	 * @return jedyna instancja klasy
	 */
	static public DisplayManager getInstance()
	{
		if (instance == null)
		{
			instance = new DisplayManager();
		}
		return instance;
	}

	/**
	 * Ustawia nowe pole do rysowania
	 * 
	 * @param frame
	 *            nowe pole do rysowania
	 */
	public void setDrawField(Graphics2D frame)
	{
		drawField = frame;
	}

	/**
	 * @return pole do rysowania
	 */
	public Graphics2D getDrawField()
	{
		return drawField;
	}

	/**
	 * Metoda uruchamiana przez zegar
	 * 
	 * @see utils.time.IClockListener#onTick(czolgisci.events.TickEvent)
	 */
	public void onTick(TickEvent e)
	{
		try
		{
			render();
		} catch (Exception e1)
		{
			e1.printStackTrace();
		}
	}

}
